import os
import sys
import datetime

from base.connection import get_db_session
from celery import Celery
from celery import platforms
from celery.utils.log import get_task_logger
from common.printer import printOrder
from common.definition import AgencyType, GoodsStatus
from conf import config
from conf.config import (FACTORY_ID, RABBITMQ_HOSTS, RABBITMQ_USER, RABBITMQ_PASSWORD, RABBITMQ_VIRTUAL_HOST,
                         REDIS_DB, REDIS_HOST, REDIS_PORT, REDIS_PWD, DOMAIN)
from debug.mqtt_subscribe import handler_mqtt_msg
from debug.mqtt_publish import send_order_mqtt_msg
from helper import template_messages, order, user, mp_helper
from helper.payment import pay_util
from helper.order import get_order, get_printer, get_print_content
from helper.coupon_helper import get_coupon

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
if BASE_DIR not in sys.path:
    sys.path.append(BASE_DIR)

logger = get_task_logger(__name__)

broker_url = "amqp://{rabbitmq_user}:{rabbitmq_password}@{rabbitmq_hosts}/{rabbitmq_virtual_host}"
broker_url = broker_url.format(rabbitmq_user=RABBITMQ_USER, rabbitmq_password=RABBITMQ_PASSWORD,
                               rabbitmq_hosts=RABBITMQ_HOSTS, rabbitmq_virtual_host=RABBITMQ_VIRTUAL_HOST)
backend_url = 'redis://:{pwd}@{host}:{port}/{db}'
backend_url = backend_url.format(pwd=REDIS_PWD, host=REDIS_HOST, port=REDIS_PORT, db=REDIS_DB)

celery = Celery('daemon.tasks', backend=backend_url, broker=broker_url)

celery.conf.task_acks_late = True
platforms.C_FORCE_ROOT = True


@celery.task
def calculate_benefit(order_id):
    logger.info("task: invoke calculate_benefit: order_id=%s" % order_id)
    ret = pay_util.calculate_benefit(order_id)
    return ret


@celery.task(name='daemon.tasks.send_order_benefit_notice')
def send_order_benefit_notice(first, order_id, order_fee, benefit, open_id, time, agency_type=AgencyType.NORMAL):
    logger.info("task: send_order_benefit_notice: order_id=%s, oid=%s" % (order_id, open_id))
    template_messages.order_benefit_notice(first, order_id, order_fee, benefit, open_id, time, agency_type)


@celery.task(name='daemon.tasks.send_balance_reward_notice')
def send_balance_reward_notice(touser, money, trade_no, am_money, first):
    logger.info("task: send_balance_reward_notice： oid=%s, trade_no=%s" % (touser, trade_no))
    template_messages.balance_reward_notice(touser, money, trade_no, am_money, first)


@celery.task(name='daemon.tasks.send_buy_success_notice')
def send_buy_success_notice(touser, trade_no):
    logger.info("task: send_buy_success_notice： oid=%s, trade_no=%s" % (touser, trade_no))
    template_messages.buy_success_notice(touser, trade_no)


@celery.task(name='daemon.tasks.send_number_remind_notice')
def send_number_remind_notice(touser, no, nickname):
    logger.info("task: send_number_remind_notice： oid=%s, number=%s" % (touser, no))
    template_messages.number_remind_notice(touser, no, nickname)


@celery.task(name='daemon.tasks.send_benefit_reward_notice')
def send_benefit_reward_notice(first, key, touser, money, order_id, is_agency=True):
    logger.info("task: send_benefit_reward_notice: touser=%s, order_id=%s, money=%s" % (touser, order_id, money))
    template_messages.benefit_reward_notice(first, key, touser, money, order_id, is_agency)


@celery.task(name='daemon.tasks.send_pay_success_notice')
def send_pay_success_notice(touser, order_id, count, fee, describe, is_self=True, name=None):
    logger.info("task: send_pay_success_notice: oid=%s, order_id=%s, fee=%s" % (touser, order_id, fee))
    template_messages.pay_success_notice(touser, order_id, count, fee, describe, is_self, name)


@celery.task(name='daemon.tasks.send_add_stock_notice')
def send_add_stock_notice(first, touser, store_name, goods_name, count, store_id):
    logger.info("task: send_add_stock_notice: sotre_id=%s,goods_name=%s" % (store_id, goods_name))
    template_messages.add_stock_notice(first, touser, store_name, goods_name, count, store_id)


@celery.task(name='daemon.tasks.cloud_print_order')
def cloud_print_order(order_id):
    """
    打印订单
    :param order_id:
    :return:
    """
    logger.info(f"task: cloud_print_order: order_id={order_id}")
    pay = get_order(order_id)
    if not pay:
        logger.info(f"订单不存在 {order_id}")
        return False
    total_fee = pay.sdef_order_fee + pay.sdef_order_balance_fee + pay.sdef_order_coupon_fee
    total_fee = "%.2f" % total_fee
    content = get_print_content(pay, total_fee)
    store_id = pay.sdef_order_store_id

    printer = get_printer(store_id)
    if not printer:
        logger.error(f"NG: 订单门店没有打印机配置 order_id={order_id}")
        return False
    sn = printer.ebf_printer_serial_number
    times = str(printer.ebf_printer_copies)
    if print_order(sn, content, order_id, store_id, times):
        logger.info("OK: print_order: sn=%s, order_id=%s, store_id=%s" % (sn, order_id, store_id))
        return True
    else:
        logger.error(f"NG: print_order: sn=%s, order_id=%s, store_id=%s" % (sn, order_id, store_id))
        return False


@celery.task(name='daemon.tasks.print_order')
def print_order(sn, content, order_id, store_id, times='1'):
    logger.info("task: print_order: sn=%s, order_id=%s, store_id=%s" % (sn, order_id, store_id))
    data = printOrder(sn, content, times)
    if data:
        if data["ret"] == 0:
            logger.info("OK: print_order:response=%s, sn=%s, order_id=%s, store_id=%s" %
                        (data, sn, order_id, store_id))
            return True
        else:
            logger.error("NG: print_order:msg=%s, sn=%s, order_id=%s, store_id=%s" %
                         (data["msg"], sn, order_id, store_id))
            return False
    else:
        # todo 打印失败发送模板消息通知店家及时处理订单
        logger.error("NG: print_order:打印订单失败,sn=%s, order_id=%s, store_id=%s" % (sn, order_id, store_id))
        return False


@celery.task(name='daemon.tasks.recive_mqtt_msg')
def recive_mqtt_msg(device_id):
    logger.info("task: recive_mqtt_msg: device_id=%s" % device_id)
    try:
        handler_mqtt_msg(device_id)
    except Exception as e:
        logger.error("NG: 接受订阅主题返回的消息失败： %s" % e)


@celery.task(name='daemon.tasks.send_order_to_mqtt')
def send_order_to_mqtt(msg, order_id, store_id):
    logger.info("task: send_order_to_mqtt: msg=%s, order_id=%s, store_id=%s" % (msg, order_id, store_id))
    try:
        result = send_order_mqtt_msg(msg)
        if result:
            logger.info("OK: send_order_to_mqtt: 成功 order_id=%s, store_id=%s" % (order_id, store_id))
        else:
            logger.error("NG: send_order_to_mqtt: 失败 order_id=%s, store_id=%s" % (order_id, store_id))
    except Exception as e:
        logger.error("NG: send_order_to_mqtt: error=%s, order_id=%s, store_id=%s" % (e, order_id, store_id))


@celery.task(name='daemon.tasks.send_new_order_notice')
def send_new_order_notice(touser, first, trade_no, time, goods, address, remark, url):
    logger.info(f"task: send_new_order_notice: order_id={trade_no}, open_id={touser}")
    template_messages.new_order_notice(touser, first, trade_no, time, goods, address, remark, url)


@celery.task(name='daemon.tasks.send_new_order_notice0')
def send_new_order_notice0(touser, room_id, store_id, order_id, first=None, value=None):
    logger.info("task: send_new_order_notice0: sotre_id=%s, order_id=%s" % (store_id, order_id))
    template_messages.new_order_notice0(touser, room_id, store_id, order_id, first, value)


@celery.task(name='daemon.tasks.send_store_order_notice')
def send_store_order_notice(order_id):
    logger.info(f"task: send_store_order_notice: order_id={order_id}")
    pay_util.send_new_order_notice(order_id)


@celery.task(name='daemon.tasks.send_cancel_order_notice')
def send_cancel_order_notice(touser, order_id, fee, goods_text, address, reason):
    logger.info(f"task: send_cancel_order_notice: touser={touser}, order_id={order_id}")
    template_messages.cancel_order_notice(touser, order_id, fee, goods_text, address, reason)


@celery.task(name='daemon.tasks.send_order_pay_success_notice')
def send_order_pay_success_notice(touser, order_id, fee, store_id, order_type, first=None, remark=None, url=None):
    logger.info(f"task: send_order_pay_success_notice: touser={touser}, order_id={order_id}")
    template_messages.order_pay_success_notice(touser, order_id, fee, store_id, order_type, first, remark, url)


@celery.task(name='daemon.tasks.send_refund_application_notice')
def send_refund_application_notice(order_id, cancel_reason=None):
    pay = order.get_order(order_id)
    touser = user.get_order_notice_oid(order_id)
    goods = order.get_goods_text(order_id)
    refund_fee = "%.2f" % (pay.sdef_order_fee + pay.sdef_order_balance_fee)
    ship_type = pay.sdef_order_ship_type
    store_id = pay.sdef_order_store_id
    room_id = pay.sdef_order_room_id
    remark = "点击了解详情"
    if ship_type == 3:
        first = f"美团因【{cancel_reason}】已取消订单配送，若骑手已取货请确认是否送回商品，无误后准予退款，请尽快处理。"
        if room_id:
            remark = f"门店: {store_id}  美团配送流水号:【{room_id}】"
    else:
        first = "你有一个订单申请退款，请尽快处理。"
        if room_id:
            remark = f"门店: {store_id}"
    logger.info(f"task: send_refund_application_notice: order_id={order_id} ")
    template_messages.refund_application_notice(touser, order_id, goods, refund_fee, first, remark)


@celery.task(name='daemon.tasks.send_refund_approval_notice')
def send_refund_approval_notice(touser, order_id, goods, order_fee, notes=None, approval="审核通过", first=None,
                                remark=None):
    logger.info(f"task: send_refund_approval_notice: order_id={order_id} ")
    template_messages.refund_approval_notice(touser, order_id, goods, order_fee, notes, approval, first, remark)


@celery.task(name='daemon.tasks.calculate_pre_benefit')
def calculate_pre_benefit(order_id):
    logger.info(f"task: calculate_pre_benefit: order_id={order_id}")
    pay_util.calculate_pre_benefit(order_id)


@celery.task(name='daemon.tasks.send_arrival_account_notice')
def send_arrival_account_notice(touser, order_id, money, first=None, value=None, remark=None):
    # (模版失效，勿用）
    logger.info(f"task: send_arrival_account_notice: order_id={order_id}, id={id}, oid={touser}")
    template_messages.arrival_account_notice(touser, order_id, money, first, value, remark)


@celery.task(name='daemon.tasks.add_store_goods')
def add_store_goods(store_id, goods_id=config.TEST_GOODS_ID, goods_count=6, goods_status=GoodsStatus.OFF_SHELF):
    """
    给门店分配商品

    add_store_goods("296", "523948088470144")

    :param store_id:
    :return:
    """
    logger.info(f"task: add_store_goods: store_id={store_id} goods_id={goods_id}")

    class Goods(object):
        pass

    class StoreGoods(object):
        pass

    session = get_db_session([
        {"db_table": "sdet_goods", "model": Goods},
        {"db_table": "sdet_store_goods", "model": StoreGoods}
    ])

    goods = session.query(Goods).filter_by(sdef_goods_id=goods_id).first()
    _goods = session.query(StoreGoods).filter_by(sdef_goods_store_id=store_id, sdef_goods_id=goods_id).first()

    if _goods:
        _goods.sdef_goods_status = goods_status  # 是否上架
        _goods.sdef_goods_count = goods_count  # 商品数量
        session.commit()
        session.close()
        logger.info(f"OK: add_store_goods: goods exist: store_id={store_id} goods_id={goods_id} count={goods_count}")
        return
    else:
        try:
            _goods = StoreGoods()
            _goods.sdef_goods_store_id = store_id
            _goods.sdef_goods_id = goods_id
            _goods.sdef_goods_factory_uid = goods.sdef_goods_factory_uid
            _goods.sdef_goods_outer_id = goods.sdef_goods_outer_id

            _goods.sdef_goods_name = goods.sdef_goods_name
            _goods.sdef_goods_price = goods.sdef_goods_price
            _goods.sdef_goods_describe = goods.sdef_goods_describe
            _goods.sdef_goods_img = goods.sdef_goods_img
            _goods.sdef_goods_img_intro = goods.sdef_goods_img_intro
            _goods.sdef_goods_thumbnail = goods.sdef_goods_thumbnail
            _goods.sdef_goods_brand_id = goods.sdef_goods_brand_id
            _goods.sdef_goods_limit_num = goods.sdef_goods_limit_num

            _goods.sdef_goods_tag = goods.sdef_goods_tag
            _goods.sdef_goods_type = goods.sdef_goods_type
            _goods.sdef_goods_from = goods.sdef_goods_from

            _goods.sdef_goods_order_num = goods.sdef_goods_order_num
            _goods.sdef_goods_is_delete = goods.sdef_goods_is_delete
            _goods.sdef_goods_is_visible = goods.sdef_goods_is_visible
            _goods.sdef_goods_type_ = goods.sdef_goods_type_
            _goods.sdef_goods_show_img = goods.sdef_goods_show_img
            _goods.sdef_goods_agency_uid = goods.sdef_goods_agency_uid
            _goods.sdef_goods_weight = goods.sdef_goods_weight

            _goods.sdef_goods_rate = goods.sdef_goods_rate
            _goods.sdef_goods_balance_rate = goods.sdef_goods_balance_rate
            _goods.sdef_goods_member_price = goods.sdef_goods_member_price
            _goods.sdef_goods_master_rate = goods.sdef_goods_master_rate
            _goods.sdef_goods_invite_rate = goods.sdef_goods_invite_rate
            _goods.sdef_goods_invite_invite_rate = goods.sdef_goods_invite_invite_rate
            _goods.sdef_goods_career_rate = goods.sdef_goods_career_rate
            _goods.sdef_goods_invite_career_rate = goods.sdef_goods_invite_career_rate
            _goods.sdef_goods_unit = goods.sdef_goods_unit
            _goods.sdef_goods_bom = goods.sdef_goods_bom
            _goods.sdef_goods_supplier = goods.sdef_goods_supplier
            _goods.sdef_goods_cost = goods.sdef_goods_cost

            _goods.sdef_goods_create_time = datetime.datetime.now()
            _goods.sdef_goods_update_time = datetime.datetime.now()

            _goods.sdef_goods_status = goods_status  # 是否上架
            _goods.sdef_goods_count = goods_count  # 商品数量

            session.add(_goods)
            session.commit()
            session.close()
            logger.info(f"OK: add_store_goods: store_id={store_id} goods_id={goods_id} count={goods_count}")
        except Exception as e:
            logger.exception(e)


@celery.task(name="daemon.tasks.send_partner_join_notice")
def send_partner_join_notice(agency_id):
    """
    发送加盟成功通知

    send_partner_join_notice(296)

    :param agency_id:
    :return:
    """

    logger.info(f"tasks.send_partner_join_notice: agency_id={agency_id}")

    class Agency(object):
        pass

    class UserAgency(object):
        pass

    session = get_db_session([
        {"db_table": "ebt_agency", "model": Agency},
        {"db_table": "ebt_user_agency", "model": UserAgency},
    ])

    agency = session.query(Agency).filter_by(ebf_agency_id=agency_id).first()
    if agency:
        agency_type = agency.ebf_agency_type
        agency_sub_type = agency.ebf_agency_sub_type
        name = agency.ebf_agency_name
        real_name = agency.ebf_agency_real_name
        phone = agency.ebf_agency_contact
        first = "恭喜成功加盟！"
        remark = "请务必点击详情查看后台\n客服电话: 18926405852(微信同号)"
        if agency_type == AgencyType.STORE:
            if agency_sub_type == 0:
                type_name = "商家"
            elif agency_sub_type == 1:
                type_name = "商家"
            elif agency_sub_type == 2:
                type_name = "行家"
            elif agency_sub_type == 3:
                type_name = "事业部"
            else:
                type_name = "商家"
            first = "恭喜成功申请加盟！"
            remark = "请准备好营业执照复印件，我们将派专人上门审核签约。签约后即开通商家后台。\n客服电话: 18926405852(微信同号)"
        elif agency_type == AgencyType.CLERK:
            type_name = "店员"
        elif agency_type == AgencyType.SALES:
            type_name = "业务员"
        else:
            type_name = "合伙人"

        # 给门店/合伙人本人发通知
        ua = session.query(UserAgency).filter_by(ebf_agency_id=agency_id).first()
        if ua:
            touser = ua.ebf_ua_bind_user_id
            template_messages.partner_join_notice(touser, first, agency_id, name, remark)
            if agency_type == AgencyType.STORE:
                # 推送门店指引图片
                shop_guide_media_id = config.SHOP_GUIDE_MEDIA_ID
                mp_helper.send_image_message(touser, shop_guide_media_id)
            else:
                # 推送合伙人指引图片
                # partner_guide_media_id = "eAhVobNVggBnmUTnnaUUI-2M6v1uds68oS9vMAIDYbc"
                # mp_helper.send_image_message(touser, partner_guide_media_id)
                # 推送合伙人指引
                mp_helper.send_text_message(touser,
                                            "恭喜您成为「海外酒庄品牌运营商」莱支好酒的合伙人！\n" +
                                            "协助酒庄推广品牌，赚外快还能免费喝酒：\n" +
                                            "一、邀满三人全退499元秒提现（可复购复退）；\n" +
                                            "二、邀请第四人起奖您150元 / 人现金；\n" +
                                            "三、被邀合伙人购酒奖您10 % 佣金；\n" +
                                            "四、分享商品赚价差（零售价 - 内供价）；\n" +
                                            "五、自购专享内供价（我的账户进入）。\n" +
                                            "邀请合伙人入伙全返499:\n" +
                                            f"https://{DOMAIN}/wx/register/invite_partner\n" +
                                            "分享消费者购酒赚价差:\n" +
                                            f"https://{DOMAIN}/wx/user/poster"
                                            )
                logger.info(f"send_text_message({touser}, 合伙人欢迎辞)")
        else:
            logger.error(f"合伙人没绑定微信！agency_id={agency_id}")

        # 给门店/合伙人上级发通知
        first1 = f"恭喜您名下有新店{name}注册成功，请及时联系对方邀请到店体验，跟进及培训越到位收益越高\n姓名：{real_name}\n电话：{phone}"
        remark1 = f"请务必认真辅导{name}，共同成长！"
        agency_id1 = agency.ebf_agency_parent_id
        agency1 = session.query(Agency).filter_by(ebf_agency_id=agency_id1).first()
        if agency1:
            ua1 = session.query(UserAgency).filter_by(ebf_agency_id=agency_id1).first()
            if ua1:
                touser1 = ua1.ebf_ua_bind_user_id
                template_messages.partner_join_notice(touser1, first1, agency_id, name, remark1)
                logger.info(f"send_partner_join_notice: agency_id={agency_id} 上级 touser={touser1}")
            else:
                logger.error(f"合伙人没绑定微信！agency_id={agency_id1}")

            # 给门店/合伙人上级的上级发通知
            # first2 = "您朋友的朋友成功加盟成为" + type_name
            # remark2 = "请务必辅导店主操作指引，共同成长！"
            # agency_id2 = agency1.ebf_agency_parent_id
            # ua2 = session.query(UserAgency).filter_by(ebf_agency_id=agency_id2).first()
            # if ua2:
            #     touser2 = ua2.ebf_ua_bind_user_id
            #     template_mesages.partner_join_notice(touser2, first2, agency_id, name, remark2)
            # else:
            #     logger.error(f"合伙人没绑定微信！agency_id={agency_id2}")
        else:
            logger.error(f"合伙人账户不存在！agency_id={agency_id1}")

        # 通知公司同事
        logger.info(f"send_partner_join_notice: agency_id={agency_id} touser={config.COMMON_NOTICE_RECEIVER}")
        template_messages.partner_join_notice(config.COMMON_NOTICE_RECEIVER, first1, agency_id, name, remark1)
    else:
        logger.error(f"合伙人账户不存在！agency_id={agency_id}")


@celery.task(name="daemon.tasks.send_lucky_draw_notice")
def send_lucky_draw_notice(touser, lucky=None, first=None, remark=None, promotion="用户幸运大奖", award="现金抵扣券", url=None):
    """
    中奖结果通知
        {{first.DATA}}
        活动：{{keyword1.DATA}}
        奖品：{{keyword2.DATA}}
        时间：{{keyword3.DATA}}
        {{remark.DATA}}
    """
    logger.info(f"tasks.send_lucky_draw_notice: touser={touser} lucky={lucky}")
    template_messages.lucky_draw_notice(touser, lucky, first, remark, promotion, award, url)


@celery.task(name="daemon.tasks.send_coupon_received_notice")
def send_coupon_received_notice(touser, coupon_name, coupon_type="代金券", create_time=None, expire_time=None,
                                remark=None):
    """
    优惠券到账通知

    优惠券名称 {{thing1.DATA}}
    优惠券类型 {{thing4.DATA}}
    到账时间  {{time5.DATA}}
    有效期至  {{time7.DATA}}
    温馨提示  {{thing8.DATA}}
    """
    logger.info(f"send_coupon_received_notice: user_id={touser} coupon={coupon_name}")
    template_messages.coupon_received_notice(touser, coupon_name, coupon_type, create_time, expire_time, remark)


@celery.task(name="daemon.tasks.send_gift_application_notice")
def send_gift_application_notice(touser):
    """
    申领成功通知
        {{first.DATA}}
        申领礼品：{{keyword1.DATA}}
        申领时间：{{keyword2.DATA}}
        申领柜台：{{keyword3.DATA}}
        {{remark.DATA}}
    """
    logger.info(f"send_gift_application_notice: touser={touser}")
    first = f"您好，您已成功领取礼品，请本人凭此消息7天内到莱支好酒生活馆门店领取（截图无效）"
    gift = f"双支装水晶红酒杯1盒"

    agency = user.UserHelper.get_user_agency(touser)
    agency_id = agency.ebf_agency_id
    shop = user.UserHelper.get_store_agency(agency_id)
    shop_address = shop.ebf_agency_address

    remark = f"感谢您关注与支持莱支好酒，欢迎到店免费品鉴体验酒庄自营美酒。"
    return template_messages.gift_application_notice(touser, first, gift, shop_address, remark)


@celery.task(name="daemon.tasks.send_signup_notice")
def send_signup_notice(recommend_user, nickname, open_id):
    return template_messages.signup_notice(recommend_user, nickname, open_id)


@celery.task(name="daemon.tasks.send_template_notice")
def send_template_notice(touser, template_id, url, data, topcolor):
    return template_messages.template_notice(touser, template_id, url, data, topcolor)


# ---------------------------------------------------------------------------------------------------------------------
# 事件异步任务入口
# ---------------------------------------------------------------------------------------------------------------------


@celery.task(name='daemon.tasks.oder_paid')
def order_paid(order_id):
    # 订单支付成功
    logger.info(f"event_received: order_paid: order_id={order_id}")

    # 锁定用户
    try:
        if config.LOCK_USER_AGENCY_ON_ORDER_PAID:
            pay_util.lock_user_agency_relation(order_id)
    except Exception as e:
        logger.exception(e)

    # 发送新订单通知
    logger.info(f"tasks.order_paid: send_new_order_notice: order_id={order_id}")
    try:
        pay_util.send_new_order_notice(order_id)
    except Exception as e:
        logger.exception(e)

    # 计算收益
    logger.info(f"tasks.order_paid: calculate_pre_benefit: order_id={order_id}")
    try:
        pay_util.calculate_pre_benefit(order_id)
        pay_util.update_complete_benefit(order_id)
        # pay_util.get_red_packet(order_id)  # 取消推荐红包 20200614
    except Exception as e:
        logger.exception(e)
    # 发收益通知
    try:
        pay_util.send_benefit_notice(order_id)
    except Exception as e:
        logger.exception(e)

    # 计算已售数量
    try:
        pay_util.count_goods_sold(order_id)
    except Exception as e:
        logger.exception(e)

    ###########################################################################
    # 新人礼订单奖励90元奖金
    # try:
    #     pay_util.new_customer_gift_order_promotion(order_id)
    # except Exception as e:
    #     logger.exception(e)

    # 新人礼首单下单即给推荐人发放可提现奖金
    try:
        pay_util.reward_recommender_cashable_balance(order_id)
    except Exception as e:
        logger.exception(e)

    # 首瓶全返余额活动 - 20221106 取消
    try:
        pay_util.first_bottle_refund_promotion(order_id)
    except Exception as e:
        logger.exception(e)

    # 特别商品返券
    try:
        pay_util.send_goods_coupon(order_id)
    except Exception as e:
        logger.exception(e)

    # 新店酬宾活动奖励处理
    try:
        pay_util.shop_opening_promotion_reward(order_id)
    except Exception as e:
        logger.exception(e)

    # 20220409 取消
    # logger.info(f"tasks.order_paid: reward_money: order_id={order_id}")
    # try:
    #     pay_util.reward_money2(order_id)  # 奖励购买私人酒庄用户及推荐人收益或余额
    #     # pay_util.return_to_giver_benefit(order_id)  # 返还送礼人5元卡费
    # except Exception as e:
    #     logger.exception(e)

    # 恒温大礼包推荐人随机红包奖励 - 20220409 取消
    # try:
    #     pay_util.recommender_random_bonus(order_id)
    # except Exception as e:
    #     logger.exception(e)

    # 样品订单返券
    # try:
    #     pay_util.send_trial_coupon(order_id)
    # except Exception as e:
    #     logger.exception(e)

    # 发放推荐优惠券-新人礼包券 - 改为关注发券 20210128
    # try:
    #     pay_util.send_recommend_coupon(order_id)
    # except Exception as e:
    #     logger.exception(e)

    # 创建用户库存 - 存酒订单处理
    # logger.info(f"tasks.order_paid: create_user_inventory: order_id={order_id}")
    # try:
    #     pay_util.create_user_inventory(order_id)  # 取消拼柜存酒，改为直接发货
    #     pass
    # except Exception as e:
    #     logger.exception(e)

    # 通知供应商/平台发货
    # try:
    #     pay_util.expedite_order_notice(order_id)
    # except Exception as e:
    #     logger.exception(e)


@celery.task(name='daemon.tasks.membership_oder_paid')
def membership_order_paid(order_id):
    # 加盟费订单支付成功
    logger.info(f"event_received: membership_order_paid: order_id={order_id}")
    pay_util.handle_partner_register_order(order_id)


@celery.task(name='daemon.tasks.order_goods_wait_pickup')
def order_goods_wait_pickup(order_id):
    # 订单待提货
    logger.info(f"event_received: order_goods_wait_pickup: order_id={order_id}")
    pay_util.send_order_pickup_notice(order_id)  # 通知供应商按物流信息发货


@celery.task(name='daemon.tasks.order_goods_shipped')
def order_goods_shipped(order_id):
    # 订单已发货
    logger.info(f"event_received: order_goods_shipped: order_id={order_id}")


@celery.task(name='daemon.tasks.oder_goods_received')
def order_goods_received(order_id):
    # 已确认收货
    logger.info(f"event_received: order_goods_received: order_id={order_id}")


@celery.task(name='daemon.tasks.oder_completed')
def order_completed(order_id):
    # 订单已完成 - 完成订单延时任务已触发/后台完成订单触发
    logger.info(f"event_received: order_paid: order_id={order_id}")

    # 新人礼首单下单即给推荐人发放可提现奖金
    try:
        pay_util.reward_recommender_cashable_balance(order_id)
    except Exception as e:
        logger.exception(e)


@celery.task(name='daemon.tasks.oder_cancelled')
def order_cancelled(order_id):
    # 订单已取消
    logger.info(f"event_received: order_cancelled: order_id={order_id}")


@celery.task(name='daemon.tasks.oder_refund_applied')
def order_refund_applied(order_id, cancel_reason=None):
    # 用户已申请退货
    logger.info(f"event_received: order_refund_applied: order_id={order_id}")
    try:
        send_refund_application_notice(order_id, cancel_reason)
    except Exception as e:
        logger.exception(e)


@celery.task(name='daemon.tasks.oder_refund_approved')
def order_refund_approved(order_id):
    # 退货已审批
    logger.info(f"event_received: order_refund_approved: order_id={order_id}")


@celery.task(name='daemon.tasks.oder_refund_rejected')
def order_refund_rejected(order_id):
    # 退货已驳回
    logger.info(f"event_received: order_refund_rejected: order_id={order_id}")


@celery.task(name='daemon.tasks.agency_registered')
def agency_registered(agency_id):
    # 合伙人已注册
    logger.info(f"event_received: agency_registered: agency_id={agency_id}")
    # 发送加盟成功通知
    send_partner_join_notice(agency_id)


@celery.task(name='daemon.tasks.store_registered')
def store_registered(store_id):
    # 商家已注册
    logger.info(f"event_received: store_registered: agency_id={store_id}")

    # 添加门店商品
    class StoreGoods(object):
        pass

    session = get_db_session([
        {"db_table": "sdet_store_goods", "model": StoreGoods}
    ])
    try:

        goods_list = session.query(StoreGoods).filter_by(
            sdef_goods_store_id=1,
            sdef_goods_status=GoodsStatus.ON_SHELF,
        ).all()

        for goods in goods_list:
            goods_id = goods.sdef_goods_id
            count = goods.sdef_goods_count
            add_store_goods(store_id, goods_id, count, GoodsStatus.ON_SHELF)
    except Exception as e:
        logger.exception(e)

    # 发送加盟成功通知
    try:
        send_partner_join_notice(store_id)
    except Exception as e:
        logger.exception(e)


@celery.task(name='daemon.tasks.clerk_registered')
def clerk_registered(agency_id):
    # 店员已注册
    logger.info(f"event_received: clerk_registered: agency_id={agency_id}")


@celery.task(name='daemon.tasks.user_registered')
def user_registered(user_id):
    # 用户已注册
    logger.info(f"event_received: user_registered: user_id={user_id}")
    # pay_util.reward_user_register(user_id)  # 取消用户扫码奖励 20191130

    # 迁移思达尔用户
    try:
        if DOMAIN == "wx.laez9.com":
            # pay_util.migrate_user(user_id)
            pass
    except Exception as e:
        logger.exception(e)

    # 增加推荐用户人数
    try:
        pay_util.add_recommend_number(user_id)
    except Exception as e:
        logger.exception(e)

    # 发送新用户礼券
    try:
        pay_util.send_new_user_coupon(user_id)
    except Exception as e:
        logger.exception(e)

    # 给新用户和推荐人充值
    # try:
    #     pay_util.recharge_new_user_and_recommender_balance(user_id)
    # except Exception as e:
    #     logger.exception(e)


@celery.task(name='daemon.tasks.create_user_coupon')
def create_user_coupon(open_id, no):
    """新用户关注公众号时分发优惠券"""
    logger.info(f"task: create_user_coupon open_id={open_id}, no={no}")
    get_coupon(open_id, no)


@celery.task(name='daemon.tasks.user_login')
def user_login(open_id, code):
    """用户登录公众号"""
    logger.info(f"task: user_login open_id={open_id}, code={code}")

    class User(object):
        pass

    session = get_db_session(
        [
            {"db_table": "ebt_user", "model": User},
        ]
    )

    try:
        user_dict = mp_helper.fetch_simple_user_info(open_id, code)
        """
        错误信息参考
        {'errcode': 41001, 'errmsg': 'access_token missing, rid: 6252a256-3f35e227-1457c18d'}
        {'errcode': 41003, 'errmsg': 'refresh_token missing, rid: 6252b333-353a2055-5ac5dfa0'}
        {'errcode': 42002, 'errmsg': 'refresh_token expired, rid: 6252be5b-7f830f01-23ff46e9'}
        {'errcode': 40013, 'errmsg': 'invalid appid, rid: 6252be5b-08f0fa76-1c016dbb'}
        """
        if "errcode" in user_dict:
            logger.error(
                f"NG: login_update_user_info: 获取用户信息出错1 open_id={open_id} user_dict={user_dict}"
            )
            # 处理令牌无效
            if user_dict.get("errcode", 0) != 0:
                access_token = mp_helper.fetch_simple_web_access_token(open_id, code, reset=True)
                user_dict = mp_helper.fetch_simple_user_info(open_id, code)
        if "errcode" in user_dict:
            logger.error(
                f"NG: login_update_user_info: 获取用户信息出错2 open_id={open_id} user_dict={user_dict}"
            )
            session.close()
            return

        #  防止张冠李戴：微信返回openid不一定是传参的open_id!
        openid = user_dict["openid"]
        user = session.query(User).filter_by(
            ebf_user_factory_id=FACTORY_ID,
            ebf_user_id=openid,
        ).first()

        if user_dict.get("subscribe", 0):
            user.ebf_user_is_subscribe = user_dict.get("subscribe", 0)

        if user_dict["unionid"]:
            user.ebf_user_account = user_dict["unionid"]
        if user_dict.get("headimgurl"):
            user.ebf_user_headurl = user_dict.get("headimgurl")
        nickname = user_dict.get("nickname", "")
        if nickname:
            user.ebf_user_nickname = nickname[:32] if len(nickname) > 32 else nickname
        user.ebf_user_gender = user_dict.get("sex", 0)
        user.ebf_user_subscribe_date = user_dict.get("subscribe_time", str(datetime.datetime.now()))
        logger.info(f"OK: login_update_user_info: open_id={open_id} info={user_dict}")
        session.commit()
    except Exception as e:
        logger.exception(f"NG: login_update_user_info: e={e} open_id={open_id}")
    session.commit()
    session.close()


if __name__ == "__main__":
    celery.start()
